diff options
| author | Fuwn <[email protected]> | 2024-02-04 20:45:14 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-02-04 20:45:14 -0800 |
| commit | 126c33520b3e426f3a12ee69d6e6f93e48edff36 (patch) | |
| tree | b36710c58e50eff267d5d7d301dd6800296afe5e /src/routes/user/[user]/badges | |
| parent | fix(badges): close if (diff) | |
| download | due.moe-126c33520b3e426f3a12ee69d6e6f93e48edff36.tar.xz due.moe-126c33520b3e426f3a12ee69d6e6f93e48edff36.zip | |
feat(badges): import mode
Diffstat (limited to 'src/routes/user/[user]/badges')
| -rw-r--r-- | src/routes/user/[user]/badges/+page.svelte | 153 |
1 files changed, 150 insertions, 3 deletions
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index a5ae83fe..523f9030 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -15,11 +15,19 @@ import Message from '$lib/Loading/Message.svelte'; import Dropdown from '$lib/Dropdown.svelte'; import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte'; + import { activityText } from '$lib/AniList/activity.js'; + import SettingHint from '$lib/Settings/SettingHint.svelte'; // import { io } from 'socket.io-client'; export let data; + interface ImportImage { + link?: string; + image: string; + } + let editMode = false; + let importMode = false; let currentUserIdentity: ReturnType<typeof userIdentity>; let error: null | string; // const socket = io(); @@ -30,7 +38,11 @@ let confirmDelete = 0; let selectedBadge: Badge | undefined = undefined; let loadError: string | null = null; + const isId = /^\d+$/.test(data.username); + let importImages: ImportImage[] | undefined = undefined; // let badgeCount = 0; + let importLinks = false; + let importCategory = ''; // $: downloadDisabled = badgeCount > 20; @@ -50,7 +62,6 @@ onMount(async () => { // socket.on('badges', (message) => (badges = message)); - const isId = /^\d+$/.test(data.username); const badger = isId ? { id: parseInt(data.username), @@ -67,7 +78,7 @@ badgesPromise = fetch(root(`/api/badges?id=${badger.id}`)); awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`)); - if (data.user) { + if (data.user && !isId) { currentUserIdentity = userIdentity(data.user); // socket.emit('badges', data.user); @@ -311,6 +322,71 @@ return url; }; + + const parsePost = async () => { + if (importImages && importImages.length > 0) importImages = undefined; + + const link = (document.querySelector('#import_activity_url') as HTMLInputElement).value; + const type = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$1'); + const id = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$2'); + + if (type !== 'activity') return null; + + let text = await activityText(parseInt(id)); + + const images: ImportImage[] = []; + + if (importLinks) { + Array.from(new DOMParser().parseFromString(text, 'text/html').querySelectorAll('a')).forEach( + (a) => { + const anchor = a as HTMLAnchorElement; + + if (anchor.querySelector('img')) { + images.push({ + link: anchor.href, + image: (anchor.querySelector('img') as HTMLImageElement).src + }); + } + } + ); + + text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, ''); + + Array.from( + new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img') + ).forEach((img) => { + const image = img as HTMLImageElement; + + images.push({ + image: image.src + }); + }); + } else { + Array.from( + new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img') + ).forEach((img) => { + const image = img as HTMLImageElement; + + images.push({ + image: image.src + }); + }); + } + + importImages = images; + }; + + const importBadges = () => + importImages?.forEach((image) => { + badgesPromise = fetch( + `/api/badges?image=${encodeURIComponent(image.image)}&post=${encodeURIComponent( + image.link || '#' + )}${importCategory.length > 0 ? `&category=${encodeURIComponent(importCategory)}` : ''}`, + { + method: 'PUT' + } + ); + }); </script> <HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} /> @@ -325,7 +401,7 @@ <Skeleton grid={true} count={100} width="150px" height="170px" /> {:then identity} - {@const isOwner = identity && identity.name === data.username} + {@const isOwner = identity && (isId ? identity.id : identity.name) === data.username} {#await badgesPromise} <Message message="Loading badges ..." /> @@ -399,6 +475,18 @@ ? $locale().user.badges.editMode.disable : $locale().user.badges.editMode.enable} </button> + <span style="margin: 0 0.625rem;">•</span> + <button + on:click={() => { + if (importMode) selectedBadge = undefined; + + importMode = !importMode; + }} + > + {importMode + ? $locale().user.badges.importMode.disable + : $locale().user.badges.importMode.enable} + </button> {#if editMode && isOwner} {@const groups = groupedBadges @@ -581,6 +669,65 @@ {/await} {/if} +{#if importMode} + <div class="popup popup-fullscreen"> + <div class="card"> + <SettingHint>Import badges from an activity post</SettingHint> + + <p /> + + <input + type="text" + placeholder={$locale().user.badges.editMode.activityURL} + id="import_activity_url" + minlength="1" + maxlength="1000" + size="20" + /> + <input + type="text" + placeholder={$locale().user.badges.editMode.category} + id="import_category" + minlength="1" + maxlength="1000" + size="20" + /> + + <p /> + + <input type="checkbox" id="import_links" name="import_links" bind:checked={importLinks} /> + Import Links + <SettingHint lineBreak> + If your images are nested in links, check this box to import the links as well. + </SettingHint> + + <p /> + + <button + on:click={() => { + importMode = false; + importImages = undefined; + }} + class="button-lined" + > + {$locale().user.badges.importMode.cancel} + </button> + <button on:click={() => parsePost()} class="button-lined" style="float: right;"> + {$locale().user.badges.importMode.fetch} + </button> + + {#if importImages && importImages.length > 0} + <p /> + + Import {importImages.length} badges? + <button on:click={() => importBadges()} class="button-lined no-shadow"> + {$locale().user.badges.importMode.import} + </button> + {/if} + </div> + </div> +{/if} + <style> /* body { margin: 0; |